<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app"></div>
    <script src="../js/v17.0.1/react.development.js"></script>
    <script src="../js/v17.0.1/react-dom.development.js"></script>
    <script src="../js/v17.0.1/babel.min.js"></script>
    <script src="../js/v17.0.1/prop-types.js"></script>
    <script type="text/babel">
        /*
            17.0.1版本 react后
            componentWillMount  组件挂载前 更改为：UNSAFE_componentWillMount
            componentWillUpdate 组件更新前 更改为：UNSAFE_componentWillUpdate
            componentWillReceiveProps 子组件接收父组件传递参数 更改为：UNSAFE_componentWillReceiveProps
        */
        class MyComponent extends React.Component {
            constructor(props) {
                super(props)
                console.log('MyComponent --- constructor')
                // 初始化测试数据
                this.state = {
                    status: true
                }
            }
            uninstallFn = () => {
                ReactDOM.unmountComponentAtNode(document.getElementById('app'))
            }
            changeStatusFn = () => {
                let { status } = this.state
                this.setState({
                    status: !status
                })
            }

            // 组件渲染钩子render
            render () {
                console.log('MyComponent --- render --- 组件渲染')
                let { status } = this.state
                return (
                    <div>
                        <button onClick={this.uninstallFn}>卸载组件</button>
                        <div>{status ? 'true' : 'false'}</div>
                        <button onClick={this.changeStatusFn}>修改status</button>
                        <button onClick={this.forceFn}>强制修改状态</button>
                    </div>
                )
            }

            // 需要将state永远同步于props,且不会再更新
            static getDerivedStateFromProps (props, state) {
                console.log('getDerivedStateFromProps', props, state)
                return null
                // return props
            }

            // 在执行更新组件前，做一些操作，返回值为快照值 或 null，快照值可以在 componentDidUpdate第三个参数中获取
            getSnapshotBeforeUpdate (props, state) {
                console.log('getSnapshotBeforeUpdate', props, state)
                // return null
                return 'mi'
            }

            // 组件挂载后
            componentDidMount () {
                console.log('MyComponent --- componentDidMount --- 组件挂载后')
            }

            // 组件将要被卸载
            componentWillUnmount () {
                console.log('MyComponent --- componentWillUnmount --- 组件将要被卸载')
            }
            /*
                控制组件更新的阀门
                每次使用setState更新状态都会去询问这个阀门
                为true则允许更新（更新后触发render函数），false为不允许更新（不触发render函数）
                如果没写这个钩子，react底层会默认加上这个钩子函数且默认return true
            */
            shouldComponentUpdate () {
                console.log('MyComponent --- shouldComponentUpdate --- 控制组件更新的阀门')
                return true
            }

            // 组件更新完毕
            componentDidUpdate (preProps, preState, Snapshot) {
                /*
                    preProps 上一个传入的props
                    preState 更新前的state
                    Snapshot getSnapshotBeforeUpdate返回的快照值
                */
                console.log('MyComponent --- componentDiaUpdate --- 组件更新完毕', preProps, preState, Snapshot)
            }
            /*
                强制更新（不受阀门控制）
            */
            forceFn = () => {
                this.forceUpdate()
            }
        }

        ReactDOM.render(<MyComponent status={false} />, document.getElementById('app'))
    </script>
</body>

</html>